package template;

/**
 * 参考: https://www.runoob.com/design-pattern/template-pattern.html
 * 意图：定义一个操作中的算法的骨架，而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
 *
 * 主要解决：一些方法通用，却在每一个子类都重新写了这一方法。
 *
 * 何时使用：有一些通用的方法。
 *
 * 如何解决：将这些通用算法抽象出来。
 *
 * 关键代码：在抽象类实现，其他步骤在子类实现。
 *
 * 应用实例： 1、在造房子的时候，地基、走线、水管都一样，只有在建筑的后期才有加壁橱加栅栏等差异。 2、西游记里面菩萨定好的 81 难，这就是一个顶层的逻辑骨架。 3、spring 中对 Hibernate 的支持，将一些已经定好的方法封装起来，比如开启事务、获取 Session、关闭 Session 等，程序员不重复写那些已经规范好的代码，直接丢一个实体就可以保存。
 * 游戏里的资源加载, 开始, 结束都一样
 *
 * 优点： 1、封装不变部分，扩展可变部分。 2、提取公共代码，便于维护。 3、行为由父类控制，子类实现。
 *
 * 缺点：每一个不同的实现都需要一个子类来实现，导致类的个数增加，使得系统更加庞大。
 *
 * 使用场景： 1、有多个子类共有的方法，且逻辑相同。 2、重要的、复杂的方法，可以考虑作为模板方法。
 *
 * 注意事项：为防止恶意操作，一般模板方法都加上 final 关键词。
 */
public class TemplatePattern {
}

abstract class Game {
    abstract void initialize();
    abstract void startPlay();
    abstract void endPlay();

    // 模板
    // 防止恶意破坏, 使用 final 修饰
    public final void play() {
        initialize();
        startPlay();
        endPlay();
    }
}

class Pokemon extends Game {

    @Override
    void initialize() {
        System.out.println("Load Pokemon Game resource");
    }

    @Override
    void startPlay() {
        System.out.println("Pokemon Game Start");
    }

    @Override
    void endPlay() {
        System.out.println("Pokemon Game End");
    }
}

class Witcher3 extends Game {

    @Override
    void initialize() {
        System.out.println("Load Witcher3 Game resource");
    }

    @Override
    void startPlay() {
        System.out.println("Witcher3 Game Start");
    }

    @Override
    void endPlay() {
        System.out.println("Witcher3 Game End");
    }
}